<template>
    <!-- 整体框架 -->
    <div style="position: absolute; margin: 0 auto; width: 1260px; display: flex; flex-wrap: wrap;">
        <!-- 分类标签区 left 开始-->
        <div class="arleft">
            <el-menu router :default-active="router.currentRoute.value.path" @select="handleMenuSelect">
                <el-menu-item :index="`/bolg`">
                    <span>全部</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/1`">
                    <span>前端技术</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/2`">
                    <span>后端开发</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/6`">
                    <span>测试技术</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/3`">
                    <span>数据库技术</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/4`">
                    <span>计算机网络</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/5`">
                    <span>操作系统</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/7`">
                    <span>大数据</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/8`">
                    <span>人工智能</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/21`">
                    <span>Android</span>
                </el-menu-item>
                <el-menu-item :index="`/bolg/22`">
                    <span>IOS</span>
                </el-menu-item>
            </el-menu>
        </div>
        <!-- 分类标签区 left 结束-->

        <!-- 文章内容区 auto 开始-->
        <!--无数据时的显示策略-->
        <div v-if="state.isNoData" class="autobox-container-ar" style="display: flex; align-items: center; justify-content: center" >
            <img src="@/assets/imge/暂无数据.jpg" alt="暂无数据" style="width: 280px; height: 280px">
        </div>
        <div v-else class="autobox-container-ar">
            <!--博客列表开始-->
            <div class="blog-list">
                <!-- 卡片 -->
                <div class="blog-item" v-for="(item, index) in state.blogList" :key="item.contentId">
                    <!-- 内容主体区域 -->
                    <div class="blog-main-content">
                        <router-link :to="`/contentdetail/${item.contentType}/${item.contentId}`">
                            <div style="display: flex; align-items: center; justify-content: space-between">
                                <!-- 标题 + 内容（左） -->
                                <div :style="item.cover ? 'width: 550px' : 'width: 700px'" >
                                    <strong class="blog-title">{{ item.title }}</strong>
                                    <div class="blog-desc">{{ truncateText(stripHtml(item.content), 150) }}</div><!-- DOMPurify 库去除HTML标签 -->
                                </div>
                                <!-- 封面图片（右） -->
                                <div class="blog-cover" v-if="item.cover">
                                    <el-image style="width: 100%; height: 100%; border-radius: 0.375rem" :src="item.cover" fit="cover" :preview-src-list="[item.cover]"/>
                                </div>
                            </div>
                        </router-link>
                        <!-- 文章信息区域（预留）：置于内容底部靠左-->
                        <div class="user-info-area">
                            <!-- 用户信息区域 靠左 -->
                            <el-avatar :src="item.user.profile_photo_path" shape="circle" :size="30" @error="errorHandler">
                                <img
                                    src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"
                                    alt="加载错误"/> <!--图片加载失败的回退行为-->
                            </el-avatar>
                            <div class="interaction-info">
                                <span>{{ item.user.username }}</span>
                                <span class="icon-item"><img src="@/assets/icon_svg/浏览量.svg" alt="icon" style="width: 20px; height: 20px">{{ item.views }}</span>
                                <div style="cursor: pointer" @click="handleLike(item.contentId, item.contentType, index)">
                                    <span v-if="isContentLiked(item.contentId)" class="icon-item"><img src="@/assets/icon_svg/实心赞.svg" alt="点赞图标" style="width: 20px; height: 20px">{{ item.likes }}</span>
                                    <span v-else class="icon-item"><img src="@/assets/icon_svg/赞.svg" alt="点赞图标" style="width: 20px; height: 20px">{{ item.likes }}</span>
                                </div>
                                <span class="icon-item"><img src="@/assets/icon_svg/_收藏.svg" alt="icon" style="width: 20px; height: 20px"> {{ item.collections }}</span>
                            </div>
                            <!--分类标签区域 靠右-->
                            <div class="blog-meta">
                                <span class="category-tag"><el-tag type="info">{{ item.category.categoryName }}</el-tag></span>
                                <span v-if="item.tags" class="tag-list"><el-tag v-for="tag in item.tags.split(',')" :key="tag" type="success">{{ tag }}</el-tag></span>
                                <span class="publish-time">{{ item.created_at.split(' ')[0] }}</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <!--博客列表结束-->
            <!-- 加载更多提示 -->
            <div ref="loadMoreTip" v-if="!state.isLoading && state.hasMore" class="load-more-tip">滑动加载更多</div>
            <div v-if="state.isLoading" class="load-more-tip">加载中...</div>
        </div>
        <!-- 文章内容区 auto 结束-->

        <!--热度排行榜 right 开始-->
        <div class="arright">
            <!-- 标题区域 -->
            <div style="width: 160px; height: 50px; border-bottom: 1px #cccbc8 solid; text-align: center; padding: 15px 0; margin: 0 auto">
                <span>热度排行榜</span>
            </div>
            <!-- 内容区域 -->
            <div style="width: 260px; position: absolute; top: 60px; margin: 0 auto;  height: 80vh">
                <!-- 卡片 -->
                <div class="heatblog-item" v-for="(heatItem, index) in state.heatContent" :key="heatItem.contentId">
                    <router-link :to="`/contentdetail/${heatItem.contentType}/${heatItem.contentId}`">
                        <!-- 内容主体区域 -->
                        <div class="blog-main-heatcontent">
                            <!-- 排名 -->
                            <div class="rank-number"
                                 :class="{
                                 'first': index === 0,
                                 'second': index === 1,
                                 'third': index === 2,
                                 'other': index > 2
                                  }">
                                {{ index + 1 }}
                            </div>
                            <div>
                                <!-- 标题 + 内容（左） -->
                                <div class="content-left">
                                    <p style="font-size: 14px; font-weight: 400; color: #1a1a1a; width: 190px; margin: 2px">{{ heatItem.title }}
                                        <!-- 热度标记 -->
                                        <span class="hot-badge" v-if="index < 3"
                                              :class="{
                                                 'one': index === 0,
                                                 'two': index === 1,
                                                 'three': index === 2
                                                  }">
                                            <span>{{ index === 0 ? '热门' : index === 1 ? '热门' : '热门' }}</span>
                                        </span>
                                    </p>
                                    <div class="view-info">
                                        <!-- 浏览量 -->
                                        <div class="view-count">
                                            <i class="fa fa-eye"></i>
                                            <span>{{ formatNumber(heatItem.views) }}</span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </router-link>
                </div>
            </div>
        </div>
        <!--热度排行榜 right 结束-->
    </div>
</template>

<script setup>
import { reactive, ref, onMounted, onUnmounted, computed } from 'vue';
import { ElMessage } from 'element-plus';
import router from "@/router/index.js";
import request from "@/utils/request.js";
import DOMPurify from 'dompurify';

//获取本地存储中的用户信息
let user;
const loginUser = localStorage.getItem('code_user');
if (loginUser) {
    // 将拿到的Json数据转化为JavaScript对象
    user = JSON.parse(loginUser);
}

// 初始化加载
onMounted(() => {
    loadBlogs(state.nextPageNum);
    window.addEventListener('scroll', handleScroll);
    selectHeat(); // 热度排行榜查询
});

// 移除滚动监听
onUnmounted(() => {
    window.removeEventListener('scroll', handleScroll);
});

// 辅助方法：格式化数字为更易读的形式
function formatNumber(num) {
    if (num >= 10000) {
        return (num / 10000).toFixed(1) + 'W';
    }
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

// 处理菜单项点击事件
const handleMenuSelect = (index) => {
    if (index === '/bolg') {
        state.blogList = allContent.value; // 展示全部数据
    } else {
        const categoryId = index.replace('/bolg/', '');
        // 根据分类 ID 筛选数据
        state.blogList = allContent.value.filter(item => item.category.categoryId === parseInt(categoryId));
    }
    state.isNoData = state.blogList.length === 0;
};

// 安全地移除HTML标签并提取纯文本
const stripHtml = (html) => {
    if (!html) return '';

    // 使用DOMPurify清理HTML，防止XSS攻击
    const clean = DOMPurify.sanitize(html);

    // 创建临时元素提取文本内容
    const temp = document.createElement('div');
    temp.innerHTML = clean;

    // 获取纯文本内容并去除多余空格
    return (temp.textContent || temp.innerText || '').trim();
};

// 截断文本并添加省略号
const truncateText = (text, length) => {
    if (text.length <= length) return text;

    // 找到最后一个完整的单词
    let truncated = text.substring(0, length);
    let lastSpace = truncated.lastIndexOf(' ');

    // 如果找到了空格，在空格处截断以避免单词被截断
    if (lastSpace !== -1) {
        truncated = truncated.substring(0, lastSpace);
    }

    return truncated + '...';
};
// 缓存所有内容
const allContent = ref([]);
const state = reactive({
    nextPageNum: 1, // 下一次加载的页码
    pageSize: 10, // 固定每页加载数量
    total: 0,
    blogList: [],  // 博客列表
    heatContent: [],   // 热度内容列表
    isLoading: false, // 加载状态
    hasMore: true, // 是否还有更多数据
    isNoData: false, // 是否有数据
});
const errorHandler = () => true //图片加载失败的回退行为
// 滚动事件处理
const loadMoreTip = ref(null);

const handleScroll = () => {
    if (state.isLoading || !state.hasMore) return;
    const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    const clientHeight = document.documentElement.clientHeight;
    const scrollHeight = document.documentElement.scrollHeight;

    // 距离底部100px时触发加载
    if (scrollTop + clientHeight >= scrollHeight - 100) {
        loadBlogs(state.nextPageNum);
    }
};

// 加载博客列表（支持无限滚动）
const loadBlogs = (pageNum, contentType = 'BOLG') => {
    state.isLoading = true;
    request.get('/api/content/selectContentPage/' + contentType, {
        params: {
            pageNum,
            pageSize: state.pageSize
        }
    }).then(res => {
        if (res.code === '200') {
            const newList = res.data.list;
            state.isNoData = res.data.list.length === 0
            // 自动分页加载
            state.blogList = [...state.blogList, ...newList]; // 合并新数据
            allContent.value = [...allContent.value, ...newList]; // 缓存新数据
            initLikedStatus(newList);  // 初始话点赞状态
            state.total = res.data.total;
            state.nextPageNum = pageNum + 1; // 准备下一页
            state.hasMore = newList.length === state.pageSize; // 判断是否还有更多数据
        } else {
            ElMessage.error(res.msg);
        }
    }).catch(error => {
        if (error.status === 403) {
            ElMessage.error("应用未授权或登录过期")
        } else {
            ElMessage.error("加载失败，请重试！")
        }
        console.error(error);
    }).finally(() => {
        state.isLoading = false;
    });
};


// 初始化内容的点赞状态
const initLikedStatus = (contentList) => {
    if (!user.user_id) return; // 用户未登录，不初始化
    // 从本地存储或服务器获取用户已点赞的内容ID列表
    request.get('/api/content/selectUserLikeAll', {
        params: { userId: user.user_id }
    }).then(res => {
        const likedRecords = res.data || [];
        // 创建一个快速查找的Map，键为"类型:ID"，值为true
        const likedMap = new Map();
        likedRecords.forEach(record => {
            likedMap.set(`${record.targetType}:${record.targetId}`, true);
        });
        // 初始化当前页内容的点赞状态
        contentList.forEach(content => {
            // 构建匹配键
            const key = `${content.contentType}:${content.contentId}`;
            // 检查是否在已点赞列表中
            const isLiked = likedMap.has(key);
            // 更新点赞状态Map
            likedContents.value.set(content.contentId, isLiked);
            // 同时更新内容对象中的likeStates字段
            content.likeStates = isLiked;
        });
    });
};
// 使用Map存储每个内容的点赞状态，键为contentId，值为布尔值
const likedContents = ref(new Map());
// 计算属性：判断内容是否已被点赞
const isContentLiked = computed(() => {
    return (contentId) => likedContents.value.get(contentId) || false;
});
// 点赞功能
const handleLike = async (contentId, contentType, index) => {
    if (user.user_id === null) {
        // 弹出登录逻辑。。。
    }
    // 获取当前内容的点赞状态
    const currentState = likedContents.value.get(contentId) || false;
    // 更新本地状态（立即更新UI）
    likedContents.value.set(contentId, !currentState);
    // 内容数据
    const contentData = {
        userId: user?.user_id || null,  // 当前浏览内容的用户
        targetId: contentId,
        targetType: contentType
    }
    // 根据当前点赞状态执行对应操作
    !currentState ? submitLike(contentId, contentType, index) : cancelLike(contentData, index) // 点赞/取消点赞
};
const submitLike = (contentId, contentType, index) => {
    try {
        request.post(`/api/content/addLike`, {
            userId: user.user_id,
            targetId: contentId,
            targetType: contentType,
        }).then(res => {
            if (res.code === '200') {
                // 更新点赞数
                state.blogList[index].likes = res.data.likes;  // 更新点赞数
                ElMessage.success('点赞成功');
            }
        })
    } catch (error) {
        ElMessage.error('点赞失败，请重试');
    }
}
const cancelLike = (like, index) => {
    try {
        request.post(`/api/content/deleteLike`, like).then(res => {
            if (res.code === '200') {
                state.blogList[index].likes = res.data.likes;  // 更新点赞数
                ElMessage.success('点赞已取消');
            }
        })
    } catch (error) {
        ElMessage.error('点赞失败，请重试');
    }
}


// 热度排行榜查询
const selectHeat = () => {
    request.get('/api/content/selectHeat', {
        params: {
            contentType: 'BOLG'
        }
    }).then(res => {
        if (res.code === '200') {
            state.heatContent = res.data
        }
    })
}

</script>

<style scoped>
/*右边排行榜样式*/
.arright {
    position: fixed;
    right: 30px;
    background-color: #fffefb;
    width: 260px;
    height: 100vh;
}
/*左边菜单栏样式*/
.arleft {
    position: fixed;
    width: 220px;
    background-color: #fffefb;
    height: 80vh;
}
/*菜单项组件样式*/
.el-menu-item {
    height: 40px;
    border-radius: 7px;
    margin: 10px;
    background-color: #fffefb;
    font-size: 14px;
}
.el-menu-item:hover {
    color: #1677ff;
    background-color: #f5f4f1;
    border-radius: 5px;
}


/*菜单激活时样式 ：高亮*/
.el-menu .is-active {
    background-color: #f5f4f1;
    color: #1677ff;
    border-radius: 5px;
}
/*中间内容区域容器：*/
.autobox-container-ar {
    position: absolute;
    right: 267px;
    width: 750px;
    box-sizing: border-box;
    background-color: #fffefb;
    min-height: 80vh;
}

/*卡片样式*/
.blog-item {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 22px;
    padding: 20px;
    border-bottom: 2px #f5f4f1 solid;
    transition: transform 0.3s, box-shadow 0.3s;
}
.blog-item:hover {
    background-color: #f5f4f1;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.10); /* 轻微外阴影 */
}
/* 用户信息区域样式 */
.user-info-area {
    width: 100%;
    display: flex;
    align-items: center;
}

/* 内容主体区域样式 */
.blog-main-content {
    display: flex;
    flex-direction: column;
}

/*标题样式*/
.blog-title {
    font-size: 18px;
    font-weight: 600;
    color: #1a1a1a;
}
/*内容样式*/
.blog-desc {
    font-size: 14px;
    line-height: 1.6;
    color: #4f4f4f;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3; /* 限制3行 */
    padding: 15px 0;
}

/* 封面图片样式 */
.blog-cover {
    flex: 0 0 180px; /* 固定宽度，不随内容缩放 */
    display: flex;
    align-items: center;
    width: 140px;
    height: 70px;
    position: absolute;
    right: 10px;
}

/*分类标签样式*/
.blog-meta {
    position: absolute;
    right: 10px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    color: #666;
    margin-left: 10px;
}

/*互动信息区样式*/
.interaction-info {
    display: flex;
    align-items: center;
    gap: 20px;
    font-size: 14px;
    color: #666;
    margin-left: 10px;
}
.icon-item {
    display: flex;
    align-items: center;
    gap: 5px;
    transition: all 0.2s;
}
/*.icon-item:hover {*/
/*    transform: scale(1.1);*/
/*}*/
.liked img {
    filter: brightness(0.8) hue-rotate(180deg); /* 点赞后图标变色 */
}


/* 加载提示样式 */
.load-more-tip {
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    color: #666;
    font-size: 0.95em;
    padding: 16px;
    border-top: 1px solid #f0f0f0;
}

.heatblog-item {
    display: flex;
    transition: transform 0.3s;
}
.heatblog-item:hover {
    background-color: #f5f4f1;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.10); /* 轻微外阴影 */
}
.blog-main-heatcontent {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px;
    border-radius: 8px;
    transition: all 0.3s ease;
}

.rank-number {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    margin-right: 10px;
    font-weight: bold;
    color: #fffefb;
}

.first {
    background: linear-gradient(to bottom right, #fbbf24, #f97316);
}

.second {
    background: linear-gradient(to bottom right, #e5e7eb, #9ca3af);
}

.third {
    background: linear-gradient(to bottom right, #b45309, rgba(120, 53, 15, 0.99));
}

.other {
    background-color: #e5e7eb;
    color: #4b5563;
}

.content-left {
    width: 260px;
    display: flex;
}

.blog-title {
    font-size: 18px;
    font-weight: 600;
    color: #1f2937;
    margin-bottom: 8px;
    display: block;
}

.view-info {
    display: flex;
    align-items: center;
    justify-content: center;
}

.view-count {
    display: flex;
    align-items: center;
    margin-right: 16px;
}

.view-count i {
    color: #9ca3af;
    margin-right: 4px;
}

.view-count span {
    font-size: 14px;
    color: #4b5563;
}

.hot-badge {
    margin-left: 16px;

}

.hot-badge span {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 500;
}

.one {
    background-color: #fee2e2;
    color: #991b1b;
    border-radius: 999px;
}

.two {
    background-color: #ffedd5;
    color: #92400e;
    border-radius: 999px;
}

.three {
    background-color: #fef3c7;
    color: #92400e;
    border-radius: 999px;
}
</style>>